/*
 * Su-yun Information Technology, Co.,Ltd CONFIDENTIAL
 *
 * (C) Copyright Su-yun Information Technology, Co.,Ltd. 2021 All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains the property of
 * Su-yun Information Technology, Co.,Ltd. The intellectual property herein
 * are protected by trade secret, patent law or copyright law. Dissemination
 * of this information or reproduction of this material is strictly forbidden
 * unless prior written permission is obtained from Su-yun Information Technology.
 *
 * https://suyunplat.com/
 *
 */
package com.xtiim.battery.discharge.common.api;

import java.util.List;

/**
 * Encapsulate common return result.
 */
public class CommonResult<T> {
    private Integer code;
    private String message;
    private Integer total;
    private T data;

    protected CommonResult() {
    }

    protected CommonResult(Integer code, String message) {
        this(code, message, null);
    }

    protected CommonResult(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
        computeTotal();
    }


    public static CommonResult success() {
        return new CommonResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage());
    }

    /**
     * Return successfully
     *
     * @param data returned data
     */
    public static <T> CommonResult<T> success(T data) {
        return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
    }

    /**
     * Return successfully with messages
     *
     * @param data returned data
     * @param  message prompt message
     */
    public static <T> CommonResult<T> success(T data, String message) {
        return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, data);
    }

    /**
     * Return wil error code
     * @param errorCode error code
     */
    public static <T> CommonResult<T> failed(IErrorCode errorCode) {
        return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);
    }

    /**
     * Return with error code and messages
     * @param errorCode error code
     * @param message error messages
     */
    public static <T> CommonResult<T> failed(IErrorCode errorCode,String message) {
        return new CommonResult<T>(errorCode.getCode(), message, null);
    }

    /**
     * Return with failed messages
     * @param message error messages
     */
    public static <T> CommonResult<T> failed(String message) {
        return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);
    }

    /**
     * Return with error code
     */
    public static <T> CommonResult<T> failed() {
        return failed(ResultCode.FAILED);
    }

    /**
     * Parameter validation failed
     */
    public static <T> CommonResult<T> validateFailed() {
        return failed(ResultCode.BAD_REQUEST);
    }

    /**
     * Parameter validation failed
     * @param message prompt error messages
     */
    public static <T> CommonResult<T> validateFailed(String message) {
        return new CommonResult<T>(ResultCode.BAD_REQUEST.getCode(), message, null);
    }

    /**
     * Not login
     *
     * @param data returned data
     * @param <T> generic type
     * @return common result
     */
    public static <T> CommonResult<T> unauthorized(T data) {
        return new CommonResult<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
    }

    /**
     * Privilege check not pass
     *
     * @param data returned data
     * @param <T>  generic type
     * @return common result
     */
    public static <T> CommonResult<T> forbidden(T data) {
        return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
    }

    /**
     * Compute the total returned size
     */
    private void computeTotal() {
        if (data == null) {
            this.total = 0;
            return;
        }

        if (List.class.isAssignableFrom(data.getClass())) {
            List list = (List) data;
            this.total = list.size();
        } else {
            this.total = 1;
        }
    }

    public long getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public T getData() {
        return data;
    }

    public int getTotal() {
        return total;
    }
}
